'''
Created on May 18, 2011

@author: Elia Contini
'''

from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.db.models.query_utils import Q
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template.context import RequestContext
from django.utils.datastructures import MultiValueDictKeyError
from django.utils.translation import ugettext as _
from datetime import datetime
import os.path
import re
import urllib

# remember repository. for deployment
from core import MEutils
from core.models import Collection, Content, Tag
from mr_edu.settings import MEDIA_ROOT
from mr_edu.settings import ABSOLUTE_PATH
from core.semantic_manager import Semantic_manager

@login_required
def collection(request, id):
    user = MEutils.getUser(request.session)
    role = MEutils.getUserRole(user)
    feedback = list()
    collection = Collection.objects.filter(id = id)[0] # TODO - what happens if collection doesn't exist?
    contents = None
    type = 'all'
    tagsList = list()
    tags = ''
    
    try:
        feedback = request.session.get('feedback')
        del request.session['feedback']
    except KeyError:
        pass
    
    # permission check
    if collection.teacher == user or user in collection.students.all():
        if request.method == 'POST':
            type = request.POST.get('filterType').strip()
            tagsList = re.compile("\s*,\s*").split(request.POST.get('filterTags').lower())
            
            tags = ''
            for i in range(0, len(tagsList)):
                tags += tagsList[i].strip()
                if i < (len(tagsList) - 1):
                    tags += ', '
        
            if type == 'all':
                if tags != '':
                    contents = Content.objects.filter(collection = id, tags__name__in = tagsList).order_by('-creation_date').distinct()
                else:
                    contents = Content.objects.filter(collection = id).order_by('-creation_date')
            elif type == 'recent':
                if tags != '':
                    contents = Content.objects.filter(collection = id, tags__name__in = tagsList).order_by('-creation_date').distinct()
                else:
                    contents = Content.objects.filter(collection = id).order_by('-creation_date')
            elif type == 'oldest':
                if tags != '':
                    contents = Content.objects.filter(collection = id, tags__name__in = tagsList).order_by('creation_date').distinct()
                else:
                    contents = Content.objects.filter(collection = id).order_by('creation_date')
            elif type == 'audio':
                # audio/ogg
                # audio/mpeg
                if tags != '':
                    contents = Content.objects.filter(Q(collection = id), Q(tags__name__in = tagsList), Q(type = 'audio/ogg') | Q(type = 'audio/mpeg')).order_by('creation_date').distinct()
                else:
                    contents = Content.objects.filter(Q(collection = id), Q(type = 'audio/ogg') | Q(type = 'audio/mpeg')).order_by('creation_date')
            elif type == 'photo':
                # image/jpeg
                if tags != '':
                    contents = Content.objects.filter(collection = id, tags__name__in = tagsList, type = 'image/jpeg').order_by('creation_date').distinct()
                else:
                    contents = Content.objects.filter(collection = id, type = 'image/jpeg').order_by('creation_date')
            elif type == 'text':
                # text/plain
                if tags != '':
                    contents = Content.objects.filter(collection = id, tags__name__in = tagsList, type = 'text/plain').order_by('creation_date').distinct()
                else:
                    contents = Content.objects.filter(collection = id, type = 'text/plain').order_by('creation_date')
            elif type == 'video':
                # video/ogg
                if tags != '':
                    contents = Content.objects.filter(collection = id, tags__name__in = tagsList, type = 'video/ogg').order_by('creation_date').distinct()
                else:
                    contents = Content.objects.filter(collection = id, type = 'video/ogg').order_by('creation_date')
        else:
            contents = Content.objects.filter(collection = id).order_by('creation_date')
    else:
        feedback.append('<p class="error">' + _("[MESSAGE] You cannot view this folder.") + '</p>')
    
    return render_to_response('common_collection.html', {'section': 'collection', 'user': user, 'userRole': role, 'id': id, 'collection': collection, 'contents': contents, 'formData': {'tags': tags, 'filter': type, }, 'feedback': feedback, }, context_instance=RequestContext(request))

@login_required
def collections(request):
    user = MEutils.getUser(request.session)
    role = MEutils.getUserRole(user)
    feedback = list()
    collections = None
    
    orderBy = request.POST.get('filter')
    if orderBy is None:
        orderBy = 'recent'
    else:
        orderBy = orderBy.strip()
    
    if role == 'teacher':
        if orderBy == 'update':
            collections = Collection.objects.filter(teacher = user).order_by('-last_modified')
        elif orderBy == 'oldest':
            collections = Collection.objects.filter(teacher = user).order_by('creation_date')
        else:
            collections = Collection.objects.filter(teacher = user).order_by('-creation_date')
    else: # student
        if orderBy == 'update':
            collections = Collection.objects.filter(students__in = [user, ]).order_by('-last_modified')
        elif orderBy == 'oldest':
            collections = Collection.objects.filter(students__in = [user, ]).order_by('creation_date')
        else:
            collections = Collection.objects.filter(students__in = [user, ]).order_by('-creation_date')
    
    try:
        feedback = request.session.get('feedback')
        del request.session['feedback']
    except KeyError:
        pass
    
    return render_to_response('common_collections.html', {'section': 'collection', 'user': user, 'userRole': role, 'collections': collections, 'formData': orderBy, 'feedback': feedback, }, context_instance=RequestContext(request))

@login_required
def content(request, id):
    user = MEutils.getUser(request.session)
    content = Content.objects.filter(id = id)[0] # TODO - what happens if content doesn't exist?
    
    # reading txt file content 
    if content.type == 'text/plain':
        source = file(MEDIA_ROOT + content.resource, 'r')
        text = ''
        for line in source.readlines():
            text += line
        source.close()
        content.resource = text
    
    return render_to_response('common_content.html', {'section': 'collection', 'user': user, 'userRole': MEutils.getUserRole(user), 'item': content, }, context_instance=RequestContext(request))

@login_required
def content_upload(request):
    user = MEutils.getUser(request.session)
    
    return render_to_response('common_content_upload.html', {'section': 'upload', 'user': user, 'userRole': MEutils.getUserRole(user), }, context_instance=RequestContext(request))

@login_required
def content_upload_from(request, source):
    user = MEutils.getUser(request.session)
    role = MEutils.getUserRole(user)
    collections = None
    feedback = list()
    data = dict() # will contain validated data ready to store
    
    if role == 'teacher':
        collections = Collection.objects.filter(teacher = user).order_by('creation_date')
    else:
        collections = Collection.objects.filter(students = user.id)
    
    if request.method == 'POST':
        name = request.POST.get('name').strip()
        file = None
        type = None
        description = request.POST.get('description').strip()
        collection = request.POST.get('collection').strip()
        tags = request.POST.get('tags').strip()
    
        # name
        if len(name) < 3:
            feedback.append('<p class="error">' + _("[MESSAGE] Name must be at least 3 characters long.") + '</p>')
        else:
            data['name'] = name
        
        # file    
        try:
            if source == 'pc':
                file = request.FILES['file']
                type = MEutils.getMediaType(file.name)
            else:
                file = request.POST.get('file').strip()
                type = MEutils.getMediaType(file)
            
            if file is not None and type is None: # check type
                feedback.append('<p class="error">' + _("[MESSAGE] The file format is not supported. Please upload a .jpg, .ogv, .ogg, .mp3 or .txt file.") + '</p>')
            else:
                data['file'] = file
                data['type'] = type[0]
        except MultiValueDictKeyError:
            feedback.append('<p class="error">' + _("[MESSAGE] You must specify a file to upload.") + '</p>')
        
        # description
        if len(description) < 8:
            feedback.append('<p class="error">' + _("[MESSAGE] Description must be at least 8 characters long.") + '</p>')
        else:
            data['description'] = description
        
        # collection
        try:
            collection = MEutils.getCollection(collection)
            
            if collection is not None:
                data['collection'] = collection
            else:
                feedback.append('<p class="error">' + _("[MESSAGE] Choose a folder.") + '</p>')
        except:
            feedback.append('<p class="error">' + _("[MESSAGE] Choose a folder.") + '</p>')            
          
        # tags
        tagList = tags.split(',')
        if len(tagList) < 3:
            feedback.append('<p class="error">' + _("[MESSAGE] Specify at least 3 tags. Tags must be separated by commas (e.g. dog, black and white, puppy)") + '</p>')
        else:
            for i in range(0, len(tagList)):
                tagList[i] = tagList[i].strip().lower() # tag will be saved in lower case
            data['tags'] = tagList
        
        # check OK      
        if len(feedback) == 0:
            # file name on server
            storagePath = MEDIA_ROOT + user.username + '/'
            fileName = datetime.now().strftime("%Y-%m-%dT%H-%M-%S") + "." + type[1] 
            data['resource'] = user.username + '/' + fileName
            
            # store file on server
            if not os.path.exists(storagePath):
                os.mkdir(storagePath)
            
            if source == 'pc':
                destination = open(storagePath + fileName, 'wb+')
                for chunk in file.chunks():
                    destination.write(chunk)
                destination.close()
            else:
                urllib.urlretrieve(file, storagePath + fileName)
            
            #save info on DB
            content = Content(
                            user = user,
                            collection = data['collection'],
                            type = data['type'],
                            name = data['name'],
                            description = data['description'],
                            resource = data['resource'],
                            )
            content.save()
            
            about = ''
            for tagName in data['tags']:
                tag = MEutils.getTag(tagName)
                if tag is not None:
                    content.tags.add(tag)
                else:
                    newTag = Tag(name = tagName)
                    newTag.save()
                    content.tags.add(newTag)
                about = about + tagName + ', '
            
            # semantic store
            uri_root = 'http://thesis.eliacontini.info/semantic/'
            userData = {'uri': uri_root + 'users/' + str(user.id),
                        }
            semantic = Semantic_manager(ABSOLUTE_PATH + 'rdfstore.db')
            #semantic.debug()
            contentData = dict()
            
            if data['type'] == 'image/jpeg':
                contentData = {'ID': str(content.id),
                         'uri': uri_root + 'image/' + str(content.id) + '/',
                         'name': data['name'],
                         'description': data['description'],
                         'about': about,
                         'creationDate': str(content.creation_date),
                         'resource': str(content.resource),
                         'contentType': str(content.type),
                         }
                semantic.insertImage(contentData, userData)
            elif data['type'] == 'text/plain':
                contentData = {'ID': str(content.id),
                         'uri': uri_root + 'text/' + str(content.id) + '/',
                         'name': data['name'],
                         'description': data['description'],
                         'about': about,
                         'creationDate': str(content.creation_date),
                         'resource': str(content.resource),
                         'contentType': str(content.type),
                         }
                semantic.insertText(contentData, userData)
            elif data['type'] == 'audio/ogg' or data['type'] == 'audio/mpeg':
                contentData = {'ID': str(content.id),
                         'uri': uri_root + 'audio/' + str(content.id) + '/',
                         'name': data['name'],
                         'description': data['description'],
                         'about': about,
                         'creationDate': str(content.creation_date),
                         'resource': str(content.resource),
                         'contentType': str(content.type),
                         }
                semantic.insertAudio(contentData, userData)
            elif data['type'] == 'video/ogg':
                contentData = {'ID': str(content.id),
                         'uri': uri_root + 'video/' + str(content.id) + '/',
                         'name': data['name'],
                         'description': data['description'],
                         'about': about,
                         'creationDate': str(content.creation_date),
                         'resource': str(content.resource),
                         'contentType': str(content.type),
                         }
                semantic.insertVideo(contentData, userData)
            
            #semantic.debug()
            del semantic
            
            feedback.append('<p class="success">' + name + ' ' +_("[MESSAGE] successfully saved.") + '</p>')
            request.session['feedback'] = feedback
            return HttpResponseRedirect("/mrEdu/" + role + "/collection/" + str(collection.id) + "/")

    return render_to_response('common_content_upload_from.html', {'section': 'upload', 'user': user, 'userRole': role, 'source': source, 'collections': collections, 'formData': data, 'feedback': feedback, }, context_instance=RequestContext(request))

@login_required
def search(request):
    user = MEutils.getUser(request.session)
    role = MEutils.getUserRole(user)
    feedback = list()
    
    try:
        feedback = request.session.get('feedback')
        del request.session['feedback']
    except KeyError:
        pass
    
    if role == 'teacher':
        collections = Collection.objects.filter(teacher = user).order_by('name')
    else: # student
        collections = Collection.objects.filter(students__in = [user, ]).order_by('name')
    
    return render_to_response('common_search.html', {'section': 'search', 'user': user, 'userRole': role, 'feedback': feedback, 'collections': collections, }, context_instance=RequestContext(request))

@login_required
def search_result(request):
    user = MEutils.getUser(request.session)
    role = MEutils.getUserRole(user)
    #feedback = list()
    keywords = ''
    
    if request.method == 'POST':
        keywords = request.POST['keywords'].strip()
        
        '''
        if keywords == '':
            feedback.append('<p class="message">' + _("[MESSAGE] Specify a keyword.") + '</p>')
            request.session['feedback'] = feedback
            return HttpResponseRedirect("/mrEdu/" + role + "/search")
        else:
        '''
        criteriaNumber = int(request.POST['criteriaNumber'].strip())
        
        criteria = dict()
        
        for i in range(1, criteriaNumber + 1):
            criterionClass = str(request.POST['criterion' + str(i)].strip())
            criterionValue = str(request.POST['criterionValue' + str(i)].strip())
            
            if not criteria.has_key(criterionClass):
                criteria[criterionClass] = list()
                criteria[criterionClass].append(criterionValue)
            else:
                criteria[criterionClass].append(criterionValue)
            
            print criterionClass + ' = ' + criterionValue
        #print criteria
        
        semantic = Semantic_manager(ABSOLUTE_PATH + 'rdfstore.db')
        contents = semantic.getContents(keywords, criteria)
        
        #semantic.debug()
        del semantic
    
    return render_to_response('common_search_result.html', {'section': 'search', 'user': user, 'userRole': role, 'keywords': keywords, 'contents': contents, }, context_instance=RequestContext(request))


def user_login(request):
    feedback = list()
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username = username, password = password)
        
        if user is not None:
            if user.is_active:
                login(request, user)    
                if MEutils.is_student(user.groups):
                    return HttpResponseRedirect('student')
                elif MEutils.is_teacher(user.groups):
                    return HttpResponseRedirect('teacher')
            else:
                feedback.append('<p class="error">' + _('[MESSAGE] Account disabled. Please contact the administrator.') + '</p>')
        else:
            feedback.append('<p class="error">' + _('[MESSAGE] Wrong username or password.') + '</p>')
    
    # TODO - if logged automatic redirect to the dashboard
    user = MEutils.getUser(request.session)
    if user is not None:
        if MEutils.is_student(user.groups):
            return HttpResponseRedirect('mrEdu/student')
        elif MEutils.is_teacher(user.groups):
            return HttpResponseRedirect('mrEdu/teacher')
    
    # http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
    return render_to_response('login.html', {'user': user, 'feedback': feedback, }, context_instance = RequestContext(request))

@login_required
def user_logout(request):
    logout(request)
    return HttpResponseRedirect('./')
